home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DKBSRC.ARJ / TRIANGLE.C < prev    next >
C/C++ Source or Header  |  1991-05-04  |  21KB  |  648 lines

  1. /*****************************************************************************
  2. *
  3. *                                      triangle.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This module implements primitives for triangles and smooth triangles.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     OMX              (613) 731-3419
  37. *     Mystic           (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:   1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     The "You Can Call Me RAY" BBS (708) 358-5611
  46. *     The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50. #include "frame.h"
  51. #include "vector.h"
  52. #include "dkbproto.h"
  53.  
  54. METHODS Triangle_Methods = {
  55.      Object_Intersect, All_Triangle_Intersections,
  56.      Inside_Triangle, Triangle_Normal,
  57.      Copy_Triangle,
  58.      Translate_Triangle, Rotate_Triangle,
  59.      Scale_Triangle, Invert_Triangle};
  60.  
  61. METHODS Smooth_Triangle_Methods = {
  62.      Object_Intersect, All_Triangle_Intersections,
  63.      Inside_Triangle, Smooth_Triangle_Normal,
  64.      Copy_Smooth_Triangle,
  65.      Translate_Smooth_Triangle, Rotate_Smooth_Triangle,
  66.      Scale_Smooth_Triangle, Invert_Smooth_Triangle};
  67.  
  68. extern TRIANGLE *Get_Triangle_Shape();
  69.  
  70. extern RAY *VP_Ray;
  71. extern long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  72.  
  73. #define max3(x,y,z) ((x>y)?((x>z)?1:3):((y>z)?2:3))
  74.  
  75. void Find_Triangle_Dominant_Axis(Triangle)
  76.    TRIANGLE *Triangle;
  77.    {
  78.    DBL x, y, z;
  79.  
  80.    x = fabs(Triangle->Normal_Vector.x);
  81.    y = fabs (Triangle->Normal_Vector.y);
  82.    z = fabs (Triangle->Normal_Vector.z);
  83.    switch (max3(x, y, z)) {
  84.       case 1: Triangle->Dominant_Axis = X_AXIS;
  85.               break;
  86.       case 2: Triangle->Dominant_Axis = Y_AXIS;
  87.               break;
  88.       case 3: Triangle->Dominant_Axis = Z_AXIS;
  89.               break;
  90.       }
  91.    }
  92.  
  93. void Compute_Smooth_Triangle (Triangle)
  94.    SMOOTH_TRIANGLE *Triangle;
  95.    {
  96.    VECTOR P3MinusP2, VTemp1, VTemp2;
  97.    DBL x, y, z, uDenominator, Proj;
  98.  
  99.    VSub (P3MinusP2, Triangle->P3, Triangle->P2);
  100.    x = fabs (P3MinusP2.x);
  101.    y = fabs (P3MinusP2.y);
  102.    z = fabs (P3MinusP2.z);
  103.  
  104.    switch (max3 (x, y, z)) {
  105.       case 1:  Triangle->vAxis = X_AXIS;
  106.                Triangle->BaseDelta = P3MinusP2.x;
  107.                break;
  108.  
  109.       case 2:  Triangle->vAxis = Y_AXIS;
  110.                Triangle->BaseDelta = P3MinusP2.y;
  111.                break;
  112.  
  113.       case 3:  Triangle->vAxis = Z_AXIS;
  114.                Triangle->BaseDelta = P3MinusP2.z;
  115.                break;
  116.       }   
  117.  
  118.    VSub (VTemp1, Triangle->P2, Triangle->P3);
  119.    VNormalize (VTemp1, VTemp1);
  120.    VSub (VTemp2, Triangle->P1, Triangle->P3);
  121.    VDot (Proj, VTemp2, VTemp1);
  122.    VScale (VTemp1, VTemp1, Proj);
  123.    VSub (Triangle->Perp, VTemp1, VTemp2);
  124.    VNormalize (Triangle->Perp, Triangle->Perp);
  125.    VDot (uDenominator, VTemp2, Triangle->Perp);
  126.    uDenominator = -1.0 / uDenominator;
  127.    VScale (Triangle->Perp, Triangle->Perp, uDenominator);
  128.    }
  129.  
  130. int Compute_Triangle (Triangle)
  131.    TRIANGLE *Triangle;
  132.    {
  133.    VECTOR V1, V2, Temp;
  134.    DBL Length;
  135.  
  136.    VSub (V1, Triangle->P1, Triangle->P2);
  137.    VSub (V2, Triangle->P3, Triangle->P2);
  138.    VCross (Triangle->Normal_Vector, V1, V2);
  139.    VLength (Length, Triangle->Normal_Vector);
  140.    if (Length < 1.0e-9)
  141.       return (0);
  142.  
  143.    /* Normalize the normal vector. */
  144.    VScale (Triangle->Normal_Vector, Triangle->Normal_Vector, 1.0/Length);
  145.  
  146.    VDot (Triangle->Distance, Triangle->Normal_Vector, Triangle->P1);
  147.    Triangle->Distance *= -1.0;
  148.    Find_Triangle_Dominant_Axis(Triangle);
  149.  
  150.    switch (Triangle->Dominant_Axis) {
  151.       case X_AXIS:
  152.          if ((Triangle->P2.y - Triangle->P3.y)*(Triangle->P2.z - Triangle->P1.z) <
  153.              (Triangle->P2.z - Triangle->P3.z)*(Triangle->P2.y - Triangle->P1.y)) {
  154.  
  155.              Temp = Triangle->P2;
  156.              Triangle->P2 = Triangle->P1;
  157.              Triangle->P1 = Temp;
  158.              if (Triangle->Type == SMOOTH_TRIANGLE_TYPE) {
  159.                 Temp = ((SMOOTH_TRIANGLE *) Triangle)->N2;
  160.                 ((SMOOTH_TRIANGLE *) Triangle)->N2 = ((SMOOTH_TRIANGLE *) Triangle)->N1;
  161.                 ((SMOOTH_TRIANGLE *) Triangle)->N1 = Temp;
  162.                 }
  163.              }
  164.           break;
  165.  
  166.       case Y_AXIS:
  167.          if ((Triangle->P2.x - Triangle->P3.x)*(Triangle->P2.z - Triangle->P1.z) <
  168.              (Triangle->P2.z - Triangle->P3.z)*(Triangle->P2.x - Triangle->P1.x)) {
  169.  
  170.              Temp = Triangle->P2;
  171.              Triangle->P2 = Triangle->P1;
  172.              Triangle->P1 = Temp;
  173.              if (Triangle->Type == SMOOTH_TRIANGLE_TYPE) {
  174.                 Temp = ((SMOOTH_TRIANGLE *) Triangle)->N2;
  175.                 ((SMOOTH_TRIANGLE *) Triangle)->N2 = ((SMOOTH_TRIANGLE *) Triangle)->N1;
  176.                 ((SMOOTH_TRIANGLE *) Triangle)->N1 = Temp;
  177.                 }
  178.              }
  179.           break;
  180.  
  181.       case Z_AXIS:
  182.          if ((Triangle->P2.x - Triangle->P3.x)*(Triangle->P2.y - Triangle->P1.y) <
  183.              (Triangle->P2.y - Triangle->P3.y)*(Triangle->P2.x - Triangle->P1.x)) {
  184.  
  185.              Temp = Triangle->P2;
  186.              Triangle->P2 = Triangle->P1;
  187.              Triangle->P1 = Temp;
  188.              if (Triangle->Type == SMOOTH_TRIANGLE_TYPE) {
  189.                 Temp = ((SMOOTH_TRIANGLE *) Triangle)->N2;
  190.                 ((SMOOTH_TRIANGLE *) Triangle)->N2 = ((SMOOTH_TRIANGLE *) Triangle)->N1;
  191.                 ((SMOOTH_TRIANGLE *) Triangle)->N1 = Temp;
  192.                 }
  193.              }
  194.           break;
  195.       }
  196.  
  197.    if (Triangle->Type == SMOOTH_TRIANGLE_TYPE)
  198.       Compute_Smooth_Triangle((SMOOTH_TRIANGLE *) Triangle);
  199.    return (1);
  200.    }
  201.  
  202. int All_Triangle_Intersections (Object, Ray, Depth_Queue)
  203.   OBJECT *Object;
  204.   RAY *Ray;
  205.   PRIOQ *Depth_Queue;
  206.   {
  207.   TRIANGLE *Shape = (TRIANGLE *) Object;
  208.   DBL Depth;
  209.   VECTOR Intersection_Point;
  210.   INTERSECTION Local_Element;
  211.  
  212.   if (Intersect_Triangle (Ray, Shape, &Depth))
  213.     {
  214.     Local_Element.Depth = Depth;
  215.     Local_Element.Object = Shape -> Parent_Object;
  216.     VScale (Intersection_Point, Ray -> Direction, Depth);
  217.     VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
  218.     Local_Element.Point = Intersection_Point;
  219.     Local_Element.Shape = (SHAPE *)Shape;
  220.     pq_add (Depth_Queue, &Local_Element);
  221.     return (TRUE);
  222.     }
  223.   return (FALSE);
  224.   }
  225.  
  226. int Intersect_Triangle (Ray, Triangle, Depth)
  227.    RAY *Ray;
  228.    TRIANGLE *Triangle;
  229.    DBL *Depth;
  230.    {
  231.    DBL NormalDotOrigin, NormalDotDirection;
  232.    DBL s, t;
  233.  
  234.    Ray_Triangle_Tests++;
  235.    if (Ray == VP_Ray) {
  236.       if (!Triangle->VPCached) {
  237.          VDot (Triangle->VPNormDotOrigin, Triangle->Normal_Vector, Ray->Initial);
  238.          Triangle->VPNormDotOrigin += Triangle->Distance;
  239.          Triangle->VPNormDotOrigin *= -1.0;
  240.          Triangle->VPCached = TRUE;
  241.          }
  242.  
  243.       VDot (NormalDotDirection, Triangle->Normal_Vector, Ray->Direction);
  244.       if ((NormalDotDirection < Small_Tolerance) &&
  245.           (NormalDotDirection > -Small_Tolerance))
  246.          return (FALSE);
  247.  
  248.       *Depth = Triangle->VPNormDotOrigin / NormalDotDirection;
  249.       }
  250.    else {
  251.       VDot (NormalDotOrigin, Triangle->Normal_Vector, Ray->Initial);
  252.       NormalDotOrigin += Triangle->Distance;
  253.       NormalDotOrigin *= -1.0;
  254.  
  255.       VDot (NormalDotDirection, Triangle->Normal_Vector, Ray->Direction);
  256.       if ((NormalDotDirection < Small_Tolerance) &&
  257.           (NormalDotDirection > -Small_Tolerance))
  258.             return (FALSE);
  259.  
  260.       *Depth = NormalDotOrigin / NormalDotDirection;
  261.       }
  262.  
  263.    if ((*Depth < Small_Tolerance) || (*Depth > Max_Distance))
  264.       return (FALSE);
  265.  
  266.    switch (Triangle->Dominant_Axis) {
  267.       case X_AXIS:
  268.          s = Ray->Initial.y + *Depth * Ray->Direction.y;
  269.          t = Ray->Initial.z + *Depth * Ray->Direction.z;
  270.  
  271.          if ((Triangle->P2.y - s)*(Triangle->P2.z - Triangle->P1.z) <
  272.              (Triangle->P2.z - t)*(Triangle->P2.y - Triangle->P1.y))
  273.             if ((int) Triangle->Inverted) {
  274.                Ray_Triangle_Tests_Succeeded++;
  275.                return (TRUE);
  276.                }
  277.             else
  278.                return (FALSE);
  279.  
  280.          if ((Triangle->P3.y - s)*(Triangle->P3.z - Triangle->P2.z) <
  281.              (Triangle->P3.z - t)*(Triangle->P3.y - Triangle->P2.y))
  282.             if ((int) Triangle->Inverted) {
  283.                Ray_Triangle_Tests_Succeeded++;
  284.                return (TRUE);
  285.                }
  286.             else
  287.                return (FALSE);
  288.  
  289.          if ((Triangle->P1.y - s)*(Triangle->P1.z - Triangle->P3.z) <
  290.              (Triangle->P1.z - t)*(Triangle->P1.y - Triangle->P3.y))
  291.             if ((int) Triangle->Inverted) {
  292.                Ray_Triangle_Tests_Succeeded++;
  293.                return (TRUE);
  294.                }
  295.             else
  296.                return (FALSE);
  297.  
  298.          if (!(int) Triangle->Inverted) {
  299.                Ray_Triangle_Tests_Succeeded++;
  300.                return (TRUE);
  301.                }
  302.             else
  303.                return (FALSE);
  304.  
  305.       case Y_AXIS:
  306.          s = Ray->Initial.x + *Depth * Ray->Direction.x;
  307.          t = Ray->Initial.z + *Depth * Ray->Direction.z;
  308.  
  309.          if ((Triangle->P2.x - s)*(Triangle->P2.z - Triangle->P1.z) <
  310.              (Triangle->P2.z - t)*(Triangle->P2.x - Triangle->P1.x))
  311.             if ((int) Triangle->Inverted) {
  312.                Ray_Triangle_Tests_Succeeded++;
  313.                return (TRUE);
  314.                }
  315.             else
  316.                return (FALSE);
  317.  
  318.          if ((Triangle->P3.x - s)*(Triangle->P3.z - Triangle->P2.z) <
  319.              (Triangle->P3.z - t)*(Triangle->P3.x - Triangle->P2.x))
  320.             if ((int) Triangle->Inverted) {
  321.                Ray_Triangle_Tests_Succeeded++;
  322.                return (TRUE);
  323.                }
  324.             else
  325.                return (FALSE);
  326.  
  327.          if ((Triangle->P1.x - s)*(Triangle->P1.z - Triangle->P3.z) <
  328.              (Triangle->P1.z - t)*(Triangle->P1.x - Triangle->P3.x))
  329.             if ((int) Triangle->Inverted) {
  330.                Ray_Triangle_Tests_Succeeded++;
  331.                return (TRUE);
  332.                }
  333.             else
  334.                return (FALSE);
  335.  
  336.          if (!(int) Triangle->Inverted) {
  337.                Ray_Triangle_Tests_Succeeded++;
  338.                return (TRUE);
  339.                }
  340.             else
  341.                return (FALSE);
  342.  
  343.       case Z_AXIS:
  344.          s = Ray->Initial.x + *Depth * Ray->Direction.x;
  345.          t = Ray->Initial.y + *Depth * Ray->Direction.y;
  346.  
  347.          if ((Triangle->P2.x - s)*(Triangle->P2.y - Triangle->P1.y) <
  348.              (Triangle->P2.y - t)*(Triangle->P2.x - Triangle->P1.x))
  349.             if ((int) Triangle->Inverted) {
  350.                Ray_Triangle_Tests_Succeeded++;
  351.                return (TRUE);
  352.                }
  353.             else
  354.                return (FALSE);
  355.  
  356.          if ((Triangle->P3.x - s)*(Triangle->P3.y - Triangle->P2.y) <
  357.              (Triangle->P3.y - t)*(Triangle->P3.x - Triangle->P2.x))
  358.             if ((int) Triangle->Inverted) {
  359.                Ray_Triangle_Tests_Succeeded++;
  360.                return (TRUE);
  361.                }
  362.             else
  363.                return (FALSE);
  364.  
  365.          if ((Triangle->P1.x - s)*(Triangle->P1.y - Triangle->P3.y) <
  366.              (Triangle->P1.y - t)*(Triangle->P1.x - Triangle->P3.x))
  367.             if ((int) Triangle->Inverted) {
  368.                Ray_Triangle_Tests_Succeeded++;
  369.                return (TRUE);
  370.                }
  371.             else
  372.                return (FALSE);
  373.  
  374.          if (!(int) Triangle->Inverted) {
  375.                Ray_Triangle_Tests_Succeeded++;
  376.                return (TRUE);
  377.                }
  378.             else
  379.                return (FALSE);
  380.  
  381.       }
  382.    return (FALSE);
  383.    }
  384.  
  385. int Inside_Triangle (Test_Point, Object)
  386.    VECTOR *Test_Point;
  387.    OBJECT *Object;
  388.    {
  389.    return (FALSE);
  390.    }
  391.  
  392. void Triangle_Normal (Result, Object, Intersection_Point)
  393.    OBJECT *Object;
  394.    VECTOR *Result, *Intersection_Point;
  395.    {
  396.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  397.  
  398.    *Result = Triangle->Normal_Vector;
  399.    }
  400.  
  401. void *Copy_Triangle (Object)
  402.    OBJECT *Object;
  403.    {
  404.    TRIANGLE *New_Shape;
  405.  
  406.    New_Shape = Get_Triangle_Shape ();
  407.    *New_Shape = * ((TRIANGLE *)Object);
  408.    New_Shape -> Next_Object = NULL;
  409.  
  410.    if (New_Shape->Shape_Texture != NULL)
  411.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  412.  
  413.    return (New_Shape);
  414.    }
  415.  
  416. void Translate_Triangle (Object, Vector)
  417.    OBJECT *Object;
  418.    VECTOR *Vector;
  419.    {
  420.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  421.    VECTOR Translation;
  422.  
  423.    VEvaluate (Translation, Triangle->Normal_Vector, *Vector);
  424.    Triangle->Distance -= Translation.x + Translation.y + Translation.z;
  425.    VAdd (Triangle->P1, Triangle->P1, *Vector)
  426.    VAdd (Triangle->P2, Triangle->P2, *Vector)
  427.    VAdd (Triangle->P3, Triangle->P3, *Vector)
  428.  
  429.    Translate_Texture (&((TRIANGLE *) Object)->Shape_Texture, Vector);
  430.    }
  431.  
  432. void Rotate_Triangle (Object, Vector)
  433.    OBJECT *Object;
  434.    VECTOR *Vector;
  435.    {
  436.    TRANSFORMATION Transformation;
  437.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  438.  
  439.    Get_Rotation_Transformation (&Transformation, Vector);
  440.    MTransformVector (&Triangle->Normal_Vector,
  441.                      &Triangle->Normal_Vector, &Transformation);
  442.    MTransformVector (&Triangle->P1, &Triangle->P1, &Transformation);
  443.    MTransformVector (&Triangle->P2, &Triangle->P2, &Transformation);
  444.    MTransformVector (&Triangle->P3, &Triangle->P3, &Transformation);
  445.    Compute_Triangle (Triangle);
  446.  
  447.    Rotate_Texture (&((TRIANGLE *) Object)->Shape_Texture, Vector);
  448.    }
  449.  
  450. void Scale_Triangle (Object, Vector)
  451.    OBJECT *Object;
  452.    VECTOR *Vector;
  453.    {
  454.    TRIANGLE *Triangle = (TRIANGLE *) Object;
  455.    DBL Length;
  456.  
  457.    Triangle->Normal_Vector.x = Triangle->Normal_Vector.x / Vector->x;
  458.    Triangle->Normal_Vector.y = Triangle->Normal_Vector.y / Vector->y;
  459.    Triangle->Normal_Vector.z = Triangle->Normal_Vector.z / Vector->z;
  460.  
  461.    VLength(Length, Triangle->Normal_Vector);
  462.    VScale (Triangle->Normal_Vector, Triangle->Normal_Vector, 1.0 / Length);
  463.    Triangle->Distance /= Length;
  464.  
  465.    VEvaluate (Triangle->P1, Triangle->P1, *Vector);
  466.    VEvaluate (Triangle->P2, Triangle->P2, *Vector);
  467.    VEvaluate (Triangle->P3, Triangle->P3, *Vector);
  468.  
  469.    Scale_Texture (&((TRIANGLE *) Object)->Shape_Texture, Vector);
  470.    }
  471.  
  472.  
  473. void Invert_Triangle (Object)
  474.    OBJECT *Object;
  475.    {
  476.    TRIANGLE *Triangle = (TRIANGLE  *) Object;
  477.  
  478.    Triangle->Inverted ^= TRUE;
  479.    }
  480.  
  481. /* Calculate the Phong-interpolated vector within the triangle
  482.    at the given intersection point. The math for this is a bit
  483.    bizarre:
  484.  
  485.     -         P1
  486.     |        /|\ \
  487.     |       / |Perp\
  488.     |      /  V  \   \
  489.     |     /   |    \   \
  490.   u |    /____|_____PI___\
  491.     |   /     |       \    \
  492.     -  P2-----|--------|----P3
  493.               Pbase    PIntersect
  494.         |-------------------|
  495.                        v
  496.  
  497.    Triangle->Perp is a unit vector from P1 to Pbase. We calculate
  498.  
  499.    u = (PI - P1) DOT Perp / ((P3 - P1) DOT Perp).
  500.  
  501.    We then calculate where the line from P1 to PI intersects the line P2 to P3:
  502.    PIntersect = (PI - P1)/u.
  503.  
  504.    We really only need one coordinate of PIntersect.  We then calculate v as:
  505.  
  506.       v = PIntersect.x / (P3.x - P2.x)
  507.  or   v = PIntersect.y / (P3.y - P2.y)
  508.  or   v = PIntersect.z / (P3.z - P2.z)
  509.  
  510.    depending on which calculation will give us the best answers.
  511.  
  512.    Once we have u and v, we can perform the normal interpolation as:
  513.  
  514.      NTemp1 = N1 + u(N2 - N1);
  515.      NTemp2 = N1 + u(N3 - N1);
  516.      Result = normalize (NTemp1 + v(NTemp2 - NTemp1))
  517.  
  518.    As always, any values which are constant for the triangle are cached
  519.    in the triangle.
  520. */
  521.  
  522. void Smooth_Triangle_Normal (Result, Object, Intersection_Point)
  523.    OBJECT *Object;
  524.    VECTOR *Result, *Intersection_Point;
  525.    {
  526.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  527.    VECTOR PIMinusP1, NTemp1, NTemp2;
  528.    DBL u = 0.0, v = 0.0;
  529.  
  530.    VSub (PIMinusP1, *Intersection_Point, Triangle->P1);
  531.    VDot (u, PIMinusP1, Triangle->Perp);
  532.    if (u < 1.0e-9) {
  533.       *Result = Triangle->N1;
  534.       return;
  535.       }
  536.  
  537.    /* BaseDelta contains P3.x-P2.x,  P3.y-P2.y, or P3.z-P2.z depending on the
  538.       value of vAxis. */
  539.  
  540.    switch (Triangle->vAxis) {
  541.       case X_AXIS:  v = (PIMinusP1.x/u + Triangle->P1.x - Triangle->P2.x) / Triangle->BaseDelta;
  542.                break;
  543.  
  544.       case Y_AXIS:  v = (PIMinusP1.y/u + Triangle->P1.y - Triangle->P2.y) / Triangle->BaseDelta;
  545.                break;
  546.  
  547.       case Z_AXIS:  v = (PIMinusP1.z/u + Triangle->P1.z - Triangle->P2.z)/ Triangle->BaseDelta;
  548.                break;
  549.       }
  550.  
  551.    VSub (NTemp1, Triangle->N2, Triangle->N1);
  552.    VScale (NTemp1, NTemp1, u);
  553.    VAdd (NTemp1, NTemp1, Triangle->N1);
  554.    VSub (NTemp2, Triangle->N3, Triangle->N1);
  555.    VScale (NTemp2, NTemp2, u);
  556.    VAdd (NTemp2, NTemp2, Triangle->N1);
  557.    VSub (*Result, NTemp2, NTemp1);
  558.    VScale (*Result, *Result, v);
  559.    VAdd (*Result, *Result, NTemp1); 
  560.    VNormalize (*Result, *Result);
  561.    }
  562.  
  563. void *Copy_Smooth_Triangle (Object)
  564.    OBJECT *Object;
  565.    {
  566.    SMOOTH_TRIANGLE *New_Shape;
  567.  
  568.    New_Shape = Get_Smooth_Triangle_Shape ();
  569.    *New_Shape = * ((SMOOTH_TRIANGLE *)Object);
  570.    New_Shape -> Next_Object = NULL;
  571.  
  572.    if (New_Shape->Shape_Texture != NULL)
  573.       New_Shape->Shape_Texture = Copy_Texture (New_Shape->Shape_Texture);
  574.  
  575.    return (New_Shape);
  576.    }
  577.  
  578. void Rotate_Smooth_Triangle (Object, Vector)
  579.    OBJECT *Object;
  580.    VECTOR *Vector;
  581.    {
  582.    TRANSFORMATION Transformation;
  583.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  584.  
  585.    Get_Rotation_Transformation (&Transformation, Vector);
  586.    MTransformVector (&Triangle->Normal_Vector,
  587.                      &Triangle->Normal_Vector, &Transformation);
  588.    MTransformVector (&Triangle->P1, &Triangle->P1, &Transformation);
  589.    MTransformVector (&Triangle->P2, &Triangle->P2, &Transformation);
  590.    MTransformVector (&Triangle->P3, &Triangle->P3, &Transformation);
  591.    MTransformVector (&Triangle->N1, &Triangle->N1, &Transformation);
  592.    MTransformVector (&Triangle->N2, &Triangle->N2, &Transformation);
  593.    MTransformVector (&Triangle->N3, &Triangle->N3, &Transformation);
  594.    Compute_Triangle ((TRIANGLE *) Triangle);
  595.  
  596.    Rotate_Texture (&((TRIANGLE *) Object)->Shape_Texture, Vector);
  597.    }
  598.  
  599. void Translate_Smooth_Triangle (Object, Vector)
  600.    OBJECT *Object;
  601.    VECTOR *Vector;
  602.    {
  603.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  604.    VECTOR Translation;
  605.  
  606.    VEvaluate (Translation, Triangle->Normal_Vector, *Vector);
  607.    Triangle->Distance -= Translation.x + Translation.y + Translation.z;
  608.    VAdd (Triangle->P1, Triangle->P1, *Vector)
  609.    VAdd (Triangle->P2, Triangle->P2, *Vector)
  610.    VAdd (Triangle->P3, Triangle->P3, *Vector)
  611.    Compute_Triangle ((TRIANGLE *) Triangle);
  612.  
  613.    Translate_Texture (&((TRIANGLE *) Object)->Shape_Texture, Vector);
  614.    }
  615.  
  616. void Scale_Smooth_Triangle (Object, Vector)
  617.    OBJECT *Object;
  618.    VECTOR *Vector;
  619.    {
  620.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *) Object;
  621.    DBL Length;
  622.  
  623.    Triangle->Normal_Vector.x = Triangle->Normal_Vector.x / Vector->x;
  624.    Triangle->Normal_Vector.y = Triangle->Normal_Vector.y / Vector->y;
  625.    Triangle->Normal_Vector.z = Triangle->Normal_Vector.z / Vector->z;
  626.  
  627.    VLength(Length, Triangle->Normal_Vector);
  628.    VScale (Triangle->Normal_Vector, Triangle->Normal_Vector, 1.0 / Length);
  629.    Triangle->Distance /= Length;
  630.  
  631.    VEvaluate (Triangle->P1, Triangle->P1, *Vector);
  632.    VEvaluate (Triangle->P2, Triangle->P2, *Vector);
  633.    VEvaluate (Triangle->P3, Triangle->P3, *Vector);
  634.    Compute_Triangle ((TRIANGLE *) Triangle);
  635.  
  636.    Scale_Texture (&((SMOOTH_TRIANGLE *) Object)->Shape_Texture, Vector);
  637.    }
  638.  
  639.  
  640. void Invert_Smooth_Triangle (Object)
  641.    OBJECT *Object;
  642.    {
  643.    SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE  *) Object;
  644.  
  645.    Triangle->Inverted ^= TRUE;
  646.    }
  647.  
  648.